package models

import (
	"fmt"
	"time"

	"github.com/beego/beego/v2/client/orm"
)

// CouponIssue 优惠券发放记录模型
type CouponIssue struct {
	BaseModel
	MemberId   int64  `orm:"column(member_id)" json:"member_id"`     // 会员ID
	CouponId   int64  `orm:"column(coupon_id)" json:"coupon_id"`     // 优惠券ID
	ActivityId int64  `orm:"column(activity_id)" json:"activity_id"` // 活动ID，0表示手动发放
	Code       string `orm:"size(50);unique" json:"code"`            // 优惠券兑换码
	Status     int8   `orm:"default(0)" json:"status"`               // 状态：0-未使用，1-已使用，2-已过期，3-已取消
	ValidFrom  int64  `orm:"" json:"valid_from"`                     // 有效期开始时间
	ValidUntil int64  `orm:"" json:"valid_until"`                    // 有效期结束时间
	UsedTime   int64  `orm:"default(0)" json:"used_time"`            // 使用时间
	OrderId    int64  `orm:"default(0)" json:"order_id"`             // 使用的订单ID
	OrderNo    string `orm:"size(50)" json:"order_no"`               // 使用的订单号
	ExpireTime int64  `orm:"default(0)" json:"expire_time"`          // 过期时间
}

// TableName 设置表名
func (c *CouponIssue) TableName() string {
	return "ss_coupon_issue"
}

// GetCouponIssueById 根据ID获取优惠券发放记录
func GetCouponIssueById(id int64) (*CouponIssue, error) {
	issue := &CouponIssue{BaseModel: BaseModel{Id: id}}
	o := orm.NewOrm()
	err := o.Read(issue)
	return issue, err
}

// GetCouponIssueByID 根据ID获取优惠券发放记录（兼容旧接口）
func GetCouponIssueByID(id int64) (*CouponIssue, error) {
	return GetCouponIssueById(id)
}

// CreateCouponIssue 创建优惠券发放记录
func CreateCouponIssue(issue *CouponIssue) (int64, error) {
	o := orm.NewOrm()
	id, err := o.Insert(issue)
	return id, err
}

// UpdateCouponIssue 更新优惠券发放记录
func UpdateCouponIssue(issue *CouponIssue) error {
	o := orm.NewOrm()
	_, err := o.Update(issue)
	return err
}

// UpdateCouponIssueStatus 更新优惠券发放记录状态
func UpdateCouponIssueStatus(id int64, status int8) error {
	o := orm.NewOrm()
	_, err := o.QueryTable(new(CouponIssue)).Filter("id", id).Update(orm.Params{
		"status":     status,
		"updated_at": time.Now().Unix(),
	})
	return err
}

// GetCouponIssueList 获取优惠券发放记录列表
func GetCouponIssueList(page, pageSize int, filters map[string]interface{}) ([]*CouponIssue, int64, error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(CouponIssue))

	// 应用过滤条件
	if memberId, ok := filters["member_id"].(int64); ok && memberId > 0 {
		qs = qs.Filter("member_id", memberId)
	}

	if couponId, ok := filters["coupon_id"].(int64); ok && couponId > 0 {
		qs = qs.Filter("coupon_id", couponId)
	}

	if activityId, ok := filters["activity_id"].(int64); ok && activityId > 0 {
		qs = qs.Filter("activity_id", activityId)
	}

	if status, ok := filters["status"].(int8); ok && status != -1 {
		qs = qs.Filter("status", status)
	}

	if code, ok := filters["code"].(string); ok && code != "" {
		qs = qs.Filter("code", code)
	}

	if startTime, ok := filters["start_time"].(int64); ok && startTime > 0 {
		qs = qs.Filter("created_at__gte", startTime)
	}

	if endTime, ok := filters["end_time"].(int64); ok && endTime > 0 {
		qs = qs.Filter("created_at__lte", endTime)
	}

	// 排除已删除的记录
	qs = qs.Filter("is_deleted", 0)

	// 获取总数
	total, _ := qs.Count()

	// 分页查询
	var issues []*CouponIssue
	_, err := qs.OrderBy("-id").Limit(pageSize, (page-1)*pageSize).All(&issues)

	return issues, total, err
}

// GetMemberCoupons 获取会员的优惠券列表
func GetMemberCoupons(memberId int64, status int8) ([]*CouponIssue, error) {
	o := orm.NewOrm()
	var issues []*CouponIssue
	qs := o.QueryTable(new(CouponIssue)).Filter("member_id", memberId).Filter("is_deleted", 0)

	if status != -1 {
		qs = qs.Filter("status", status)
	}

	_, err := qs.OrderBy("-id").All(&issues)
	return issues, err
}

// CheckCouponUsable 检查优惠券是否可用
func CheckCouponUsable(issueId int64, amount float64) (bool, string) {
	o := orm.NewOrm()

	// 获取优惠券发放记录
	issue := &CouponIssue{BaseModel: BaseModel{Id: issueId}}
	err := o.Read(issue)
	if err != nil {
		return false, "优惠券不存在"
	}

	// 检查优惠券状态
	if issue.Status != 0 {
		return false, "优惠券已使用或已过期"
	}

	// 检查有效期
	now := time.Now().Unix()
	if now < issue.ValidFrom {
		return false, "优惠券未到使用时间"
	}
	if now > issue.ValidUntil {
		return false, "优惠券已过期"
	}

	// 获取优惠券信息
	coupon, err := GetCouponById(issue.CouponId)
	if err != nil {
		return false, "获取优惠券信息失败"
	}

	// 检查最低消费
	if coupon.MinConsume > 0 && amount < coupon.MinConsume {
		return false, fmt.Sprintf("订单金额未达到最低消费要求: %.2f", coupon.MinConsume)
	}

	return true, ""
}

// UseCoupon 使用优惠券
func UseCoupon(issueId int64, orderId int64, orderNo string) error {
	o := orm.NewOrm()
	issue := &CouponIssue{BaseModel: BaseModel{Id: issueId}}
	if err := o.Read(issue); err != nil {
		return err
	}

	issue.Status = 1 // 已使用
	issue.UsedTime = time.Now().Unix()
	issue.OrderId = orderId
	issue.OrderNo = orderNo
	issue.UpdatedAt = time.Now().Unix()

	_, err := o.Update(issue)
	if err != nil {
		return err
	}

	// 更新优惠券使用数量
	return IncreaseCouponUsedCount(issue.CouponId)
}

// GetMemberCouponIssueCount 获取会员已领取指定优惠券的数量
func GetMemberCouponIssueCount(memberId, couponId int64) (int64, error) {
	o := orm.NewOrm()
	return o.QueryTable(new(CouponIssue)).
		Filter("member_id", memberId).
		Filter("coupon_id", couponId).
		Filter("is_deleted", 0).
		Count()
}

// UseCouponTx 在事务中使用优惠券
func UseCouponTx2(tx orm.TxOrmer, issueId int64, memberId int64, orderId int64, orderNo string) error {
	issue := &CouponIssue{BaseModel: BaseModel{Id: issueId}}
	err := tx.Read(issue)
	if err != nil {
		return fmt.Errorf("获取优惠券信息失败: %v", err)
	}

	if issue.MemberId != memberId {
		return fmt.Errorf("无权使用该优惠券")
	}

	if issue.Status != 0 {
		return fmt.Errorf("优惠券已使用或已过期")
	}

	now := time.Now().Unix()
	if now < issue.ValidFrom || now > issue.ValidUntil {
		return fmt.Errorf("优惠券不在有效期内")
	}

	issue.Status = 1 // 已使用
	issue.UsedTime = now
	issue.OrderId = orderId
	issue.OrderNo = orderNo
	issue.UpdatedAt = now

	_, err = tx.Update(issue)
	if err != nil {
		return fmt.Errorf("更新优惠券状态失败: %v", err)
	}

	// 更新优惠券模板的使用数量
	_, err = tx.QueryTable(new(Coupon)).Filter("id", issue.CouponId).Update(orm.Params{
		"used_count": orm.ColValue(orm.ColAdd, 1),
		"updated_at": now,
	})
	if err != nil {
		return fmt.Errorf("更新优惠券使用数量失败: %v", err)
	}

	return nil
}

// GetCouponIssueByCode 根据优惠券码获取优惠券发放记录
func GetCouponIssueByCode(code string) (*CouponIssue, error) {
	if code == "" {
		return nil, orm.ErrNoRows
	}

	o := orm.NewOrm()
	issue := &CouponIssue{Code: code}
	err := o.Read(issue, "Code")
	return issue, err
}
